package cn.yangke.basic.service.impl;

import cn.yangke.basic.constants.BaseConstant;
import cn.yangke.basic.dto.RegisterDto;
import cn.yangke.basic.exception.BusinessException;
import cn.yangke.basic.service.IVerifyCodeService;
import cn.yangke.basic.util.SendSmsUtil;
import cn.yangke.basic.util.StrUtils;
import cn.yangke.basic.util.VerifyCodeUtils;
import cn.yangke.user.domain.User;
import cn.yangke.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * @Author YangKe
 * @Date 2022/6/15 18:57
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private UserMapper userMapper;

    /**
     * 图形验证码
     * @param key 图形验证码的uuid做的key
     * @return
     */
    @Override
    public String imageCode(String key) {
        //校验前段传回来的uuid作为key,是否为空
        if(!StringUtils.hasLength(key)){
            throw new BusinessException("key不能为空!");
        }
        //使用工具类随机生成4位数的验证码
        String code = StrUtils.getComplexRandomString(4);
        //
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);

        return VerifyCodeUtils.VerifyCode(100,40,code);
    }

    @Override
    public void smsCode(RegisterDto dto) {
        //根据type区分功能
        String type = dto.getType();
        if("register".equals(type)){
            //注册短信验证码
            registerSmsCode(dto);
        }else if("binder".equals(type)){
            //绑定短信验证码
            binderSmsCode(dto);
        }





    }

    /**
     * 注册验证码
     * @param dto
     */
    private void registerSmsCode(RegisterDto dto) {
        //前段输入的手机号
        String phone = dto.getPhone();
        //图形验证码的key
        String imageCodeKey = dto.getImageCodeKey();
        //前段输入的图形验证码
        String imageCodeValue = dto.getImageCodeValue();
        //一：校验
        //1.空校验
        if(StringUtils.isEmpty(phone)
                ||StringUtils.isEmpty(imageCodeKey)
                ||StringUtils.isEmpty(imageCodeValue)
        ){
            throw new BusinessException("输入的内容不能为空!!!");
        }
        //2.校验图形验证码，根据imageCodeKey从redis获取图形验证码
        Object imageCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        //。获取不到 图形验证码过期，重新获取
        if(imageCodeTmp == null){
            throw new BusinessException("图形验证码已过期,请重新刷新!!");
        }
        //。获取到了，比对图形验证码是否正确
        if(!imageCodeTmp.toString().equalsIgnoreCase(imageCodeValue)){
            //- 不正确，提示输入图形验证码错误
            throw new BusinessException("请输入正确的图形验证码!!!");
        }
        //- 正确，往下走
        //3.校验手机号是否注册过了
        User userTmp = userMapper.loadByPhone(phone);
        //。注册过了，滚去登录
        if(userTmp != null){
            throw new BusinessException("该手机号已被注册,请直接登录!");
        }
        //。没有注册过，往下走
        //二：短信验证码逻辑
        //1.根据手机号拼接key，159:register，从redis获取曾今可能发送的短信验证码
        String key = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX + phone;
        //发送验证码逻辑
        sendSmsCode(phone,key);

    }

    /**
     * 绑定验证码
     * @param dto
     */
    private void binderSmsCode(RegisterDto dto) {
        //前段输入的手机号
        String phone = dto.getPhone();
        //一：校验
        //1.空校验
        if(StringUtils.isEmpty(phone)
        ){
            throw new BusinessException("输入的内容不能为空!!!");
        }
        String key = BaseConstant.RegisterConstants.BINDER_SMS_PREFIX + dto.getPhone();
        //发送验证码逻辑
        sendSmsCode(phone,key);
    }

    /**
     * 校验发送验证
     * @param key
     */
    private void sendSmsCode(String phone,String key) {
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        //提前声明
        String smsCode = "";
        //1.1 获取到了
        if(smsCodeTmp != null){
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
            //1.1.1 校验是否过了一分钟重发时间 value  9527:232468742341657213
            //。小于一分钟  哥屋恩
            if(System.currentTimeMillis() - oldTime <= 1*60*1000){
                throw new BusinessException("小伙子,不要搞事情哦!");
            }
            //。大于一分中 （还没有到3分钟，验证码还有效），
            //获取还没过期的验证码
            smsCode = smsCodeTmp.toString().split(":")[0];
        }else {
            //1.2 获取不到
            //1.2.1.生成新的短信验证码
            smsCode = StrUtils.getRandomString(6);
        }
        //生成新的SMSCodeValue=smsCode:时间戳
        String smsCodeValue = smsCode+":"+System.currentTimeMillis();
        //3.存储redis 设置一个过期时间
        redisTemplate.opsForValue().set(key,smsCodeValue,3,TimeUnit.MINUTES);
        //4.发送短信
        SendSmsUtil.sendSms(phone,smsCode);

    }
}
